package service

import (
	"fmt"
	"gin_gorm_oj/define"
	"gin_gorm_oj/help"
	"gin_gorm_oj/modles"
	"github.com/gin-gonic/gin"
	"github.com/streadway/amqp"
	"gorm.io/gorm"
	"net/http"
	"strconv"
	"time"
)

// GetUserDetail
// @Tags 公共方法
// @Summary 用户详情
// @Param identity query string false "problem identity"
// @Success 200 {string} json "{"code":"200","data":""}"
// @Router /user-detail [get]
func GetUserDetail(c *gin.Context) {
	identity := c.Query("identity")
	if identity == "" {
		c.JSON(200, gin.H{
			"code": -1,
			"msg":  "用户唯一标识不能为空",
		})
		return
	}
	data := new(modles.User)
	err := modles.DB.Where("identity=?", identity).First(&data).Error
	if err != nil {
		c.JSON(200, gin.H{
			"code": -1,
			"msg":  "用户数据获取错误" + err.Error(),
		})
		return
	}
	c.JSON(200, gin.H{
		"code": 0,
		"data": data,
	})
}

// Login
// @Tags 公共方法
// @Summary 用户登录
// @Param username formData string false "username"
// @Param password formData string false "username"
// @Success 200 {string} json "{"code":"200","data":""}"
// @Router /login [post]
func Login(c *gin.Context) {
	username := c.PostForm("username")
	password := c.PostForm("password")
	if username == "" || password == "" {
		c.JSON(200, gin.H{
			"code": -1,
			"msg":  "用户名和密码不能为空",
		})
		return
	}
	//mdd5加密
	password = help.GetMd5(password)

	data := new(modles.User)
	err := modles.DB.Where("name=? AND password=?", username, password).First(&data).Error
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			c.JSON(200, gin.H{
				"code": -1,
				"msg":  "用户名密码错误",
			})
			return
		}
		c.JSON(200, gin.H{
			"code": -1,
			"msg":  "内部错误" + err.Error(),
		})
	}

	token, err := help.GenerateToken(data.Identity, data.Name, data.IsAdmin)
	if err != nil {
		c.JSON(200, gin.H{
			"code": -1,
			"msg":  "token error" + err.Error(),
		})
	}
	c.JSON(200, gin.H{
		"code":  200,
		"token": token,
	})
}

// Register
// @Tags 公共方法
// @Summary 用户注册
// @Param mail formData string false "mail"
// @Param code formData string false "code"
// @Param name formData string false "name"
// @Param password formData string false "password"
// @Param phone formData string false "phone"
// @Success 200 {string} json "{"code":"200","data":""}"
// @Router /register [post]
func Register(c *gin.Context) {
	mail := c.PostForm("mail")
	code := c.PostForm("code")
	name := c.PostForm("name")
	password := c.PostForm("password")
	phone := c.PostForm("phone")
	if name == "" || mail == "" || code == "" || password == "" {
		c.JSON(200, gin.H{
			"code": -1,
			"msg":  "信息为空",
		})
		return
	}
	//判断邮箱是否存在
	var cnt int64
	err3 := modles.DB.Where("mail", mail).Model(new(modles.User)).Count(&cnt).Error
	if err3 != nil {
		c.JSON(200, gin.H{
			"code": -1,
			"msg":  "判断是否存在错误" + err3.Error(),
		})
		return
	}
	if cnt > 0 {
		c.JSON(200, gin.H{
			"code": -1,
			"msg":  "该邮箱已被注册",
		})
		return
	}
	modles.RDB.Set(c, mail, help.GetRand(), 0)
	//验证码码是否正确
	sysCode, err := modles.RDB.Get(c, mail).Result()
	fmt.Println(sysCode)
	if err != nil {
		c.JSON(200, gin.H{
			"code": -1,
			"msg":  "get  redis错误" + err.Error(),
		})
	}

	//数据的插入
	//验证验证码
	//if syscode != code {
	//	c.JSON(200, gin.H{
	//		"code": -1,
	//		"msg":  "验证码不正确",
	//	})
	//	return
	//}
	data := &modles.User{
		Name:     name,
		Mail:     mail,
		Phone:    phone,
		Password: help.GetMd5(password),
		Identity: help.GetUUID(),
	}

	err2 := modles.DB.Create(data).Error
	if err != nil {
		c.JSON(200, gin.H{
			"code": -1,
			"msg":  "添加用户错误" + err2.Error(),
		})
	}
	//生成token
	token, err1 := help.GenerateToken(data.Identity, data.Name, data.IsAdmin)
	if err1 != nil {
		c.JSON(200, gin.H{
			"code": -1,
			"msg":  "token error" + err1.Error(),
		})
	}
	c.JSON(200, gin.H{
		"code":  200,
		"token": token,
	})
}

// GetRankList
// @Tags 公共方法
// @Summary 用户排行榜
// @Param size query int false "size"
// @Param page query int false "page"
// @Success 200 {string} json "{"code":"200","data":""}"
// @Router /rank-list [get]
func GetRankList(c *gin.Context) {
	page, _ := strconv.Atoi(c.DefaultQuery("page", define.DefaultPage))
	size, _ := strconv.Atoi(c.DefaultQuery("size", define.DefaultSize))
	page = (page - 1) * size
	var count int64
	list := make([]*modles.User, 0)
	err := modles.DB.Model(new(modles.User)).Count(&count).Order("finish_problem_num desc,submit_num ASC").
		Offset(page).Limit(size).Find(&list).Error
	if err != nil {
		c.JSON(200, gin.H{
			"code": -1,
			"msg":  "获取用户排行榜数据错误" + err.Error(),
		})
		return
	}

	c.JSON(200, gin.H{
		"code":  200,
		"msg":   list,
		"count": count,
	})
}

func Follow(c *gin.Context) {
	followIdentity, _ := strconv.Atoi(c.PostForm("follow"))
	token := c.GetHeader("Authorization")

	userClaims, _ := help.AnalyseToken(token)
	identity, _ := strconv.Atoi(userClaims.Identity)
	var cnt int64
	err := modles.DB.Where("user_identity", identity).Where("follow_identity", followIdentity).Model(new(modles.Relation)).Count(&cnt).Error
	if err != nil {
		c.JSON(200, gin.H{
			"code":  -1,
			"error": err.Error(),
		})
	}
	if cnt > 0 {
		c.JSON(200, gin.H{
			"code":          0,
			"data":          "已关注",
			"user_identity": identity,
		})
		return
	}
	relation := &modles.Relation{
		UserIdentity:   identity,
		FollowIdentity: followIdentity,
		RelationTime:   time.Now(),
	}
	if err := modles.DB.Transaction(func(tx *gorm.DB) error {
		var user modles.User
		err := tx.Model(&user).Where("identity=? ", followIdentity).UpdateColumn("follower_count", gorm.Expr("follower_count + ?", 1)).Error
		if err != nil {
			return err
		}
		err1 := tx.Model(&user).Where("identity=? ", identity).UpdateColumn("follow_count", gorm.Expr("follow_count + ?", 1)).Error
		if err1 != nil {
			return err1
		}
		tx.Create(relation)
		return nil
	}); err != nil {
		c.JSON(200, gin.H{
			"code": -1,
			"msg":  "更新问题错误" + err.Error(),
		})
		return
	}
	mq := modles.Mq
	mq.Channel.Publish(
		mq.Exchange,   // 交换器名
		mq.RoutingKey, // routing key
		false,         // 是否返回消息(匹配队列)，如果为true, 会根据binding规则匹配queue，如未匹配queue，则把发送的消息返回给发送者
		false,         // 是否返回消息(匹配消费者)，如果为true, 消息发送到queue后发现没有绑定消费者，则把发送的消息返回给发送者
		amqp.Publishing{ // 发送的消息，固定有消息体和一些额外的消息头，包中提供了封装对象
			ContentType: "text/plain", // 消息内容的类型
			Body:        []byte("关注"), // 消息内容
		},
	)

	c.JSON(200, gin.H{
		"code": 0,
		"data": "关注成功",
	})
}
func GetUsersPage(c *gin.Context) {
	var user []modles.User
	Db := modles.DB
	page, _ := strconv.Atoi(c.Query("page"))
	pageSize, _ := strconv.Atoi(c.Query("page_size"))
	if name, isExist := c.GetQuery("name"); isExist == true {
		Db = Db.Where("name = ?", name)
	}
	if page > 0 && pageSize > 0 {
		Db = Db.Limit(pageSize).Offset((page - 1) * pageSize)
	}
	if err := Db.Find(&user).Error; err != nil {
		fmt.Println(err.Error())
	}
	c.JSON(http.StatusOK, gin.H{
		"data": user,
	})
}
